﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.ApplicationServer.Caching;
using VerifyArgs;
using System.Runtime.Caching;

namespace EP.Caching.Providers {
	public class AzureCacheProvider : ICacheProvider {
		private static DataCacheFactory _CacheFactory;
		private static DataCache _Cache;

		static AzureCacheProvider() {
			// Cache host(s)
			var servers = new List<DataCacheServerEndpoint>(1){
				new DataCacheServerEndpoint("localhost", 22233)
			};

			// Configuration
			var configuration = new DataCacheFactoryConfiguration {
				Servers = servers,
				LocalCacheProperties = new DataCacheLocalCacheProperties(1000,
					new TimeSpan(0, 10, 0),
					DataCacheLocalCacheInvalidationPolicy.TimeoutBased)
			};

			// Disable tracing to avoid informational / verbose messages on the web page
			DataCacheClientLogManager.ChangeLogLevel(TraceLevel.Off);

			_CacheFactory = new DataCacheFactory(configuration);
			_Cache = _CacheFactory.GetCache("default");
		}

		#region ICacheProvider Members
		public TimeSpan? SlidingTimeout { get; set; }

		public bool SupportsAbsoluteTimeout { get { return false; } }
		public DateTimeOffset? AbsoluteTimeout {
			get { throw new NotSupportedException(); }
			set { throw new NotSupportedException(); }
		}

		public bool SupportsChangeMonitors { get { return false; } }
		public IList<ChangeMonitor> Monitors {
			get { throw new NotSupportedException(); }
		}

		public void Add<T>(string key, T value) {
			Verify.Args(new { key }).NotNullOrEmpty();

			if (SlidingTimeout != null && SlidingTimeout.HasValue)
				_Cache.Add(key, value, SlidingTimeout.Value);
			else
				_Cache.Add(key, value);
		}

		public bool Contains(string key) {
			Verify.Args(new { key }).NotNullOrEmpty();

			return _Cache.Get(key) != null;
		}

		public object Get(string key) {
			Verify.Args(new { key }).NotNullOrEmpty();

			return _Cache.Get(key);
		}
		public T Get<T>(string key) where T : class, IConvertible {
			Verify.Args(new { key }).NotNullOrEmpty();

			if (typeof(T) is IConvertible)
				return (T)Convert.ChangeType(_Cache.Get(key), typeof(T));
			return _Cache.Get(key) as T;
		}

		public void Remove(string key) {
			Verify.Args(new { key }).NotNullOrEmpty();

			_Cache.Remove(key);
		}
		#endregion
	}
}
